/**
 * simple_plugin.c - 简单的示例插件
 * 
 * 演示如何使用纯eBPF架构的钩子框架创建插件
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "../../include/hook_framework.h"

/* 插件数据结构 */
typedef struct {
    char log_file[256];     /* 日志文件路径 */
    int log_all_file_ops;   /* 是否记录所有文件操作 */
    int log_all_network_ops;/* 是否记录所有网络操作 */
} plugin_config_t;

/* 插件配置 */
static plugin_config_t g_config = {
    .log_file = "hook_simple_plugin.log",
    .log_all_file_ops = 1,
    .log_all_network_ops = 1
};

/* 记录文件操作 */
static int log_file_operation(const char* op, const char* path) {
    time_t now = time(NULL);
    char timestamp[64];
    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
    
    return helper_log_to_file(g_config.log_file, 
                           "[%s] 文件操作: %s '%s'", 
                           timestamp, op, path ? path : "(未知)");
}

/* 记录网络操作 */
static int log_network_operation(const char* op, const char* addr, int port) {
    time_t now = time(NULL);
    char timestamp[64];
    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
    
    return helper_log_to_file(g_config.log_file, 
                           "[%s] 网络操作: %s %s:%d", 
                           timestamp, op, addr ? addr : "(未知)", port);
}

/* ==== 回调函数 ==== */

/* 打开文件前置回调 */
static int open_pre_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    const char* pathname = (const char*)context->args[0];
    int flags = (int)(long)context->args[1];
    
    /* 记录文件操作 */
    log_file_operation("打开", pathname);
    
    /* 允许操作继续 */
    return HOOK_CONTINUE;
}

/* 连接网络前置回调 */
static int connect_pre_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int sockfd = (int)(long)context->args[0];
    const struct sockaddr* addr = (const struct sockaddr*)context->args[1];
    
    /* 只处理IPv4连接 */
    if (addr->sa_family == AF_INET) {
        const struct sockaddr_in* addr_in = (const struct sockaddr_in*)addr;
        char ip_str[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &(addr_in->sin_addr), ip_str, INET_ADDRSTRLEN);
        int port = ntohs(addr_in->sin_port);
        
        log_network_operation("连接", ip_str, port);
        
        /* 可选：检查是否为危险IP地址，如有必要，阻止连接 */
        if (helper_is_loopback(ip_str) && !helper_has_env("ALLOW_LOOPBACK")) {
            log_message(LOG_WARN, "阻止连接到环回地址: %s:%d", ip_str, port);
            return HOOK_STOP; /* 阻止连接 */
        }
    }
    
    /* 允许连接继续 */
    return HOOK_CONTINUE;
}

/* 执行命令前置回调 */
static int system_pre_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    const char* command = (const char*)context->args[0];
    
    /* 记录命令执行 */
    log_file_operation("执行命令", command);
    
    /* 可选：检查是否包含危险命令，如有必要，阻止执行 */
    if (strstr(command, "rm -rf") || strstr(command, "mkfs") || 
        strstr(command, "dd if=/dev/zero") || strstr(command, ":(){ :|:& };:")) {
        log_message(LOG_WARN, "阻止执行危险命令: %s", command);
        return HOOK_STOP; /* 阻止执行 */
    }
    
    /* 允许命令执行继续 */
    return HOOK_CONTINUE;
}

/* ==== 使用宏定义钩子函数 ==== */

/* 拦截fopen函数 */
DEFINE_HOOK2(FILE*, fopen, const char*, const char*);

/* 拦截system函数 */
DEFINE_HOOK1(int, system, const char*);

/* ==== 插件初始化和清理 ==== */

/* 插件初始化函数 */
__attribute__((visibility("default")))
int plugin_init(void) {
    /* 输出插件信息 */
    log_message(LOG_INFO, "简单插件初始化");
    
    /* 从环境变量加载配置 */
    const char* log_file = getenv("SIMPLE_PLUGIN_LOG_FILE");
    if (log_file) {
        strncpy(g_config.log_file, log_file, sizeof(g_config.log_file) - 1);
    }
    
    const char* log_file_ops = getenv("SIMPLE_PLUGIN_LOG_FILE_OPS");
    if (log_file_ops) {
        g_config.log_all_file_ops = atoi(log_file_ops);
    }
    
    const char* log_network_ops = getenv("SIMPLE_PLUGIN_LOG_NETWORK_OPS");
    if (log_network_ops) {
        g_config.log_all_network_ops = atoi(log_network_ops);
    }
    
    /* 注册回调函数 */
    register_pre_callback("open", open_pre_callback, NULL, 100);
    register_pre_callback("open64", open_pre_callback, NULL, 100);
    register_pre_callback("connect", connect_pre_callback, NULL, 100);
    register_pre_callback("system", system_pre_callback, NULL, 100);
    
    /* 记录插件已加载 */
    helper_log_to_file(g_config.log_file, "简单插件已加载，版本: 1.0.0");
    
    return 1;
}

/* 插件清理函数 */
__attribute__((visibility("default")))
void plugin_cleanup(void) {
    log_message(LOG_INFO, "简单插件清理");
    helper_log_to_file(g_config.log_file, "简单插件已卸载");
} 